/*
package com.devshephard.framework.config;

import com.baomidou.mybatisplus.autoconfigure.MybatisPlusProperties;
import com.baomidou.mybatisplus.core.config.GlobalConfig;
import com.baomidou.mybatisplus.core.toolkit.GlobalConfigUtils;
import com.baomidou.mybatisplus.core.toolkit.SystemClock;
import com.devshephard.framework.util.ContextHolder;
import org.apache.ibatis.binding.MapperRegistry;
import org.apache.ibatis.builder.xml.XMLMapperBuilder;
import org.apache.ibatis.builder.xml.XMLMapperEntityResolver;
import org.apache.ibatis.executor.ErrorContext;
import org.apache.ibatis.executor.keygen.SelectKeyGenerator;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.logging.Log;
import org.apache.ibatis.logging.LogFactory;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.parsing.XNode;
import org.apache.ibatis.parsing.XPathParser;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.util.ResourceUtils;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.*;

*/
/**
 * 切莫用于生产环境（后果自负）,
 * <p>
 * Mybatis 映射文件热加载（发生变动后自动重新加载）.
 * </p>
 * <p>
 * 方便开发时使用，不用每次修改xml文件后都要去重启应用.
 * </p>
 *//*

public class MybatisMapperRefresh {
    private static final Log logger = LogFactory.getLog(MybatisMapperRefresh.class);
    */
/**
     * 记录jar包存在的mapper
     *//*

    private static final Map<String, List<Resource>> jarMapper = new HashMap<>();
    private SqlSessionFactory sqlSessionFactory;
    private Resource[] mapperLocations;
    private Configuration configuration;
    private volatile Long beforeTime = SystemClock.now();
    */
/**
     * xml文件目录
     *//*

    private Set<String> fileSet;
    private MybatisPlusProperties mybatisPlusProperties;

    public MybatisMapperRefresh(SqlSessionFactory sqlSessionFactory) {
        this.setSqlSessionFactory(sqlSessionFactory);
    }

    public MybatisMapperRefresh(Resource[] mapperLocations, SqlSessionFactory sqlSessionFactory) {
        this.mapperLocations = mapperLocations.clone();
        this.setSqlSessionFactory(sqlSessionFactory);
    }

    public void initFileSet() {
        if (mapperLocations == null || mapperLocations.length == 0) {
            scanNewMapperXml();
        }
        final GlobalConfig globalConfig = GlobalConfigUtils.getGlobalConfig(configuration);
        fileSet = new HashSet<>();

        for (Resource mapperLocation : mapperLocations) {
            try {
                if (ResourceUtils.isJarURL(mapperLocation.getURL())) {
                    String key =
                        new UrlResource(ResourceUtils.extractJarFileURL(mapperLocation.getURL())).getFile().getPath();
                    fileSet.add(key);
                    if (jarMapper.get(key) != null) {
                        jarMapper.get(key).add(mapperLocation);
                    } else {
                        List<Resource> resourcesList = new ArrayList<>();
                        resourcesList.add(mapperLocation);
                        jarMapper.put(key, resourcesList);
                    }
                } else {
                    fileSet.add(mapperLocation.getFile().getPath());
                }
            } catch (IOException ioException) {
                ioException.printStackTrace();
            }
        }
    }

    public void refreshChangeFile() {
        if (fileSet == null || fileSet.size() == 0) {
            initFileSet();
        }
        try {
            final Long tmpBeforeTime = beforeTime;
            for (String filePath : fileSet) {
                File file = new File(filePath);
                if (file.isFile() && file.lastModified() > tmpBeforeTime) {
                    if (file.lastModified() > beforeTime) {
                        // 记录上次重新加载时间防止重复加载已经重载的文件
                        beforeTime = file.lastModified();
                    }
                    List<Resource> removeList = jarMapper.get(filePath);
                    if (removeList != null && !removeList.isEmpty()) {
                        for (Resource resource : removeList) {
                            refresh(resource);
                        }
                    } else {
                        refresh(new FileSystemResource(file));
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    */
/**
     * 刷新mapper
     *
     * @throws Exception
     *//*

    @SuppressWarnings("rawtypes")
    private void refresh(Resource resource)
        throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
        this.configuration = sqlSessionFactory.getConfiguration();
        boolean isSupper = configuration.getClass().getSuperclass() == Configuration.class;
        try {
            Field loadedResourcesField =
                isSupper ? configuration.getClass().getSuperclass().getDeclaredField("loadedResources")
                    : configuration.getClass().getDeclaredField("loadedResources");
            loadedResourcesField.setAccessible(true);
            Set loadedResourcesSet = ((Set)loadedResourcesField.get(configuration));
            XPathParser xPathParser = new XPathParser(resource.getInputStream(), true, configuration.getVariables(),
                new XMLMapperEntityResolver());
            XNode context = xPathParser.evalNode("/mapper");
            String namespace = context.getStringAttribute("namespace");
            Field field = MapperRegistry.class.getDeclaredField("knownMappers");
            field.setAccessible(true);
            Map mapConfig = (Map)field.get(configuration.getMapperRegistry());
            Collection<String> mappedStatementNames = configuration.getMappedStatementNames();

            mapConfig.remove(Resources.classForName(namespace));
            loadedResourcesSet.remove(resource.toString());
            configuration.getCacheNames().remove(namespace);

            cleanParameterMap(context.evalNodes("/mapper/parameterMap"), namespace);
            cleanResultMap(context.evalNodes("/mapper/resultMap"), namespace);
            cleanKeyGenerators(context.evalNodes("insert|update|select"), namespace);
            cleanSqlElement(context.evalNodes("/mapper/sql"), namespace);
            XMLMapperBuilder xmlMapperBuilder =
                new XMLMapperBuilder(resource.getInputStream(), sqlSessionFactory.getConfiguration(),
                    resource.toString(), sqlSessionFactory.getConfiguration().getSqlFragments());
            xmlMapperBuilder.parse();
            logger.debug(resource + "' reloaded!");
        } catch (IOException e) {
            logger.error("Refresh IOException :" + e.getMessage());
        } finally {
            ErrorContext.instance().reset();
        }
    }

    */
/**
     * 清理parameterMap
     *
     * @param list
     * @param namespace
     *//*

    private void cleanParameterMap(List<XNode> list, String namespace) {
        for (XNode parameterMapNode : list) {
            String id = parameterMapNode.getStringAttribute("id");
            configuration.getParameterMaps().remove(namespace + "." + id);
        }
    }

    */
/**
     * 清理resultMap
     *
     * @param list
     * @param namespace
     *//*

    private void cleanResultMap(List<XNode> list, String namespace) {
        for (XNode resultMapNode : list) {
            String id = resultMapNode.getStringAttribute("id", resultMapNode.getValueBasedIdentifier());
            configuration.getResultMapNames().remove(id);
            configuration.getResultMapNames().remove(namespace + "." + id);
            clearResultMap(resultMapNode, namespace);
        }
    }

    private void clearResultMap(XNode xNode, String namespace) {
        for (XNode resultChild : xNode.getChildren()) {
            if ("association".equals(resultChild.getName()) || "collection".equals(resultChild.getName())
                || "case".equals(resultChild.getName())) {
                if (resultChild.getStringAttribute("select") == null) {
                    configuration.getResultMapNames()
                        .remove(resultChild.getStringAttribute("id", resultChild.getValueBasedIdentifier()));
                    configuration.getResultMapNames().remove(
                        namespace + "." + resultChild.getStringAttribute("id", resultChild.getValueBasedIdentifier()));
                    if (resultChild.getChildren() != null && !resultChild.getChildren().isEmpty()) {
                        clearResultMap(resultChild, namespace);
                    }
                }
            }
        }
    }

    */
/**
     * 清理selectKey
     *
     * @param list
     * @param namespace
     *//*

    private void cleanKeyGenerators(List<XNode> list, String namespace) {
        for (XNode context : list) {
            String id = context.getStringAttribute("id");
            configuration.getKeyGeneratorNames().remove(id + SelectKeyGenerator.SELECT_KEY_SUFFIX);
            configuration.getKeyGeneratorNames().remove(namespace + "." + id + SelectKeyGenerator.SELECT_KEY_SUFFIX);

            Collection<MappedStatement> mappedStatements = configuration.getMappedStatements();
            List<MappedStatement> objects = new ArrayList<>();
            Iterator<MappedStatement> it = mappedStatements.iterator();
            while (it.hasNext()) {
                Object object = it.next();
                if (object instanceof MappedStatement) {
                    MappedStatement mappedStatement = (MappedStatement)object;
                    if (mappedStatement.getId().equals(namespace + "." + id)) {
                        objects.add(mappedStatement);
                    }
                }
            }
            mappedStatements.removeAll(objects);
        }
    }

    */
/**
     * 清理sql节点缓存
     *
     * @param list
     * @param namespace
     *//*

    private void cleanSqlElement(List<XNode> list, String namespace) {
        for (XNode context : list) {
            String id = context.getStringAttribute("id");
            configuration.getSqlFragments().remove(id);
            configuration.getSqlFragments().remove(namespace + "." + id);
        }
    }

    */
/**
     * 扫描xml文件所在的路径
     *
     *//*

    public MybatisMapperRefresh scanNewMapperXml() {
        Set<Resource> resourceSet = new HashSet<>();
        for (String location : mybatisPlusProperties.getMapperLocations()) {
            try {
                resourceSet.addAll(Arrays.asList(ContextHolder.getApplicationContext().getResources(location)));
            } catch (Exception e) {
            }
        }
        this.mapperLocations = resourceSet.toArray(new Resource[resourceSet.size()]);
        return this;
    }

    public static MybatisMapperRefresh getInstance() {
        if (SINGLETON_HUNGARY.sqlSessionFactory == null) {
            SINGLETON_HUNGARY
                .setSqlSessionFactory(ContextHolder.getApplicationContext().getBean(SqlSessionFactory.class));
        }
        if (SINGLETON_HUNGARY.mybatisPlusProperties == null) {
            SINGLETON_HUNGARY.mybatisPlusProperties =
                ContextHolder.getApplicationContext().getBean(MybatisPlusProperties.class);
        }
        return SINGLETON_HUNGARY;
    }

    public static MybatisMapperRefresh getInstance(Resource[] mapperLocations, SqlSessionFactory sqlSessionFactory) {
        SINGLETON_HUNGARY.setResource(mapperLocations);
        SINGLETON_HUNGARY.setSqlSessionFactory(sqlSessionFactory);
        return getInstance();
    }

    public MybatisMapperRefresh setResource(Resource[] mapperLocations) {
        this.mapperLocations = mapperLocations.clone();
        return this;
    }

    public MybatisMapperRefresh setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
        this.sqlSessionFactory = sqlSessionFactory;
        if (sqlSessionFactory != null) {
            this.configuration = sqlSessionFactory.getConfiguration();
        }
        return this;
    }

    private static final MybatisMapperRefresh SINGLETON_HUNGARY = new MybatisMapperRefresh(new Resource[0], null);
}*/
